        TTL     > FS15 : CLI decoding and associated routines

                GBLL    $debugcli
$debugcli       SETL    $debug :LAND: $False

; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
; In    os_cliptr, Y -> string

UKCommand ROUT

        Push    cliptr          ; Preserve zp
        LDA     fstmp
        PHA

        TYA
        CLC
        ADC     os_cliptr
        TAX
        LDA     os_cliptr+1
        ADCIM   0
        TAY                     ; YX -> string 

        LDAIM   ut_cmd          ; From UKCommand
        JSR     Decode          ; CC -> finished processing

        PLA
        STA     fstmp
        Pull    cliptr

        BCS     #FT99           ; Claim service if CC
        JMP     ClaimService

99      JMP     EndService

; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
; Used by UKCommand and FSCommand

; In    YX -> string
;       A = caller id

; Out   CC -> claimed
;       CS -> not claimed
;       cliptr,regs,flags corrupt

exhausted ; Table exhausted. Go home

        SEC                     ; Indicate nothing doing
        RTS


Decode  ROUT

        STA     fstmp           ; Save caller id

        STXY    cliptr
 [ $debugcli
 JSR xystring
 JSR donewline
 ]

        LDXIM   &FF

scanthiscomloop
        INX                     ; Step onto first byte of command entry
 [ $debugcli
 TXA
 JSR debugA
 LDAAX comtable
 JSR debugA
 JSR donewline
 ]
        LDAAX   comtable
        BEQ     exhausted       ; End of table ?
        AND     fstmp           ; Check caller id bit
        BNE     callok
        SEC                     ; Indicate no match after skip
        BRA     skipt_loop      ; Skip entry if wrong caller

callok  INX                     ; Skip byte
        LDYIM   0               ; Start from beginning of passed command again

checkcomloop
        LDAAX   comtable
        BMI     endofourword
        EORIY   cliptr
        ANDIM   &DF
        BNE     nomatch
        INX
        INY
        BRA     checkcomloop

nomatch LDAIY   cliptr
        INY                     ; Advance in case it's '.'
        CMPIM   "."
        BEQ     goodmatch

badmatch
        SEC
        BRA     skiptoend

endofourword
        ASLA
        BMI     goodmatch
        LDAIY   cliptr
        CMPIM   "A"             ; Allows BASIC. , BASIC1 etc for compatibility
        BCS     badmatch

goodmatch
        CLC

skiptoend
        DEX
skipt_loop
        INX
        LDAAX   comtable
        BPL     skipt_loop
        BCS     scanthiscomloop
;;;     BCC     foundmatch

;;;foundmatch
        ASLA
        ANDIM   &7F
        TAX

; In    cliptr -> command name (easy to pass to Arthur)
;       cliptr, Y -> command tail (stripped)

 [ $debugcli
 JSR vstring ; corrupts A
 = "pcmd "
 NOP
 ]
        LDAAX   comrouts+1
 [ $debugcli
 JSR debugA
 ]
        PHA
        LDAAX   comrouts
 [ $debugcli
 JSR debugA
 ]
        PHA
        JMP     skipspaces      ; Set flags, returning to required routine

; Routine returns CS if extra processing needed
; or CC if we should claim service

; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

skips_next
        INY
skipspaces
        LDAIY   cliptr
        CMPIM   " "
        BEQ     skips_next
        CMPIM   CR
        RTS

; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
; Check end of line ok (ie null or just spaces)

bcm_skipspaces
        JSR     skipspaces
        BNE     qBadCommand
        RTS

qBadCommand
        LDXIM   :LSB: eBadCommand
        LDYIM   :MSB: eBadCommand
        JMP     CauseBRK

eBadCommand
        =       247, "Bad command", 0

; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
; In    YX -> error block

CauseBRK ROUT

        STX     fstmp
        STY     fstmp+1

        LDAIM   cBRK
        STA     stack-1

        LDYIM   0
10      LDAIY   fstmp           ; Filing system error number never zero !
        STAAY   stack
        INY
        TAX
        BNE     #BT10

        JMP     stack-1         ; Cause BRK

; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
; Skip spaces and optional comma and read decimal number

; Out   EQ if no more

nextdecimal ROUT

        JSR     skipspaces
        BEQ     #FT70           ; RTS

        CMPIM   ","
        BNE     readd2

        INY

; .............................................................................
; Read decimal number from cliptr,Y

; Out   NE. A = number

readdecimal

        JSR     skipspaces

; .............................................................................
; In    A = (cliptr),Y

readd2  CMPIM   "&"             ; Hex number ?
        BEQ     #FT80

        LDXIM   0
        STX     number
        STX     number+1

10      LDAIY   cliptr
        SEC
        SBCIM   "0"
        BCC     #FT50           ; Crap
        CMPIM   9+1             ; In 00..09 ?
        BCS     #FT50           ; Crap
        PHA

        LDA     number          ; number *:= 2. CClear from CMP
        ROLA
        BCS     bad_n2          ; Overflowed ?
        STA     number+1        ; number *:= 5
        ROLA
        BCS     bad_n2          ; Overflowed ?
        ROLA
        BCS     bad_n2          ; Overflowed ?
        ADC     number+1        ; CClear
        BCS     bad_n2          ; Overflowed ?
        STA     number+1
        PLA                     ; number +:= digit
        ADC     number+1
        STA     number
        BCS     bad_n2          ; Overflowed ?

        INX                     ; A digit has been read
        INY
        BNE     #BT10           ; Safer than BRA

50      CPXIM   0               ; Must have read a digit
        BEQ     bad_n2

60      LDA     number          ; resultis number
        TSX                     ; NE
70      RTS


80      INY                     ; Skip '&'
        JSR     readhex

        LDA     number+1        ; Too big ?
        BEQ     #BT60


bad_n2  JMP     qBadNumber

; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
; Read hex number from cliptr,Y

; Out   X = digit read; EQ -> no following args, NE -> got another arg

readhex ROUT

        LDXIM   0
        STX     number
        STX     number+1

10      LDAIY   cliptr
        SEC
        SBCIM   "0"
        BCC     #FT50           ; Crap
        CMPIM   9+1             ; In 00..09 ?
        BCC     #FT20           ; Ok
        ANDIM   &DF
        SBCIM   &07             ; CSet; Get rid of colon thru @ symbols
        CMPIM   10              ; Must be in 0A .. 0F here
        BCC     #FT50           ; Crap
        CMPIM   15+1
        BCS     #FT50           ; Crap

20      ASLA                    ; Good number
        ASLA
        ASLA
        ASLA
        LDXIM   &03

40      ASLA
        ROL     number
        ROL     number+1
        BCS     bad_n2          ; Overflowed ?
        DEX
        BPL     #BT40

        INY                     ; X  = &FF a ce moment
        BNE     #BT10           ; Safer than BRA

50      JMP     skipspaces      ; and return ...

; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

needhex JSR     readhex
        PHP
        CPXIM   0
        BEQ     bad_n2          ; If no digits read
        PLP                     ; Else return skipspaces result
        RTS

; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
; In    cliptr, Y -> command tail

; Out   cliptr -> command tail

AddCliPtrY ROUT

        PHA
        TYA
        CLC
        ADC     cliptr
        STA     cliptr
        BCC     #FT90
        INC     cliptr+1
90      PLA
        RTS

; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
; In    cliptr, Y -> command tail

; Out   YX -> command tail

AddYXCliPtrY ROUT

        PHA
        TYA
        CLC
        ADC     cliptr
        TAX
        LDAIM   0
        ADC     cliptr+1
        TAY
        PLA
        RTS

; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
; First: Allowable caller id(s)

ut_cmd  *       1 :SHL: 0
dfs_cmd *       1 :SHL: 1
nfs_cmd *       1 :SHL: 2
adfs_cmd *      1 :SHL: 3
arfs_cmd *      1 :SHL: 4

nondfs_cmd *    nfs_cmd :OR: adfs_cmd :OR: arfs_cmd
fs_cmd     *    dfs_cmd :OR: nondfs_cmd

; Last: b7 -> end of word marker, b6..0 = cmdno

comtable
        =       nondfs_cmd, "ACCESS",  !12   ; (*AC.)
        =       dfs_cmd,    "ACCESS",  !35   ; (*AC.)
        =       ut_cmd,     "ADFS",    !08   ; (*A.)
        =       ut_cmd,     "ARFS",    !07   ; (*AR.)
        =       adfs_cmd :OR: arfs_cmd, "BACK",!22 ; (*BAC.)
        =       nondfs_cmd, "BYE",     !25   ; (*BY.)
        =       ut_cmd,     "CLOSE",   !20   ; (*C.)
        =       nondfs_cmd, "CDIR",    !23   ; (*CD.)
        =       adfs_cmd :OR: arfs_cmd, "COMPACT",!26 ; (*CO.)
        =       dfs_cmd,    "COMPACT", !33   ; (*CO.)
        =       nondfs_cmd, "CREATE",  !18   ; (*CR.)
        =       ut_cmd,     "DISC",    !04   ; (*D.)
        =       ut_cmd,     "DISK",    !04   ; same as *disc
        =       adfs_cmd :OR: arfs_cmd, "DISMOUNT",!28 ; (*DISM.)
        =       nondfs_cmd, "DELETE",  !14   ; (*DE.)
        =       dfs_cmd,    "DELETE",  !36   ; (*DE.)
        =       nondfs_cmd, "DIR",     !09   ; (*DI.)
        =       dfs_cmd,    "DIR",     !30   ; (*DI.)
        =       dfs_cmd,    "DRIVE",   !11   ; (*DR.)
        =       dfs_cmd,    "ENABLE",  !06   ; (*EN.)
        =       nondfs_cmd, "EX",      !29   ; (*EX)
        =       dfs_cmd,    "EX",      !32   ; (*EX)
        =       ut_cmd,     "GO",      !01   ; (*G.)
        =       nondfs_cmd, "INFO",    !13   ; (*I.)
        =       dfs_cmd,    "INFO",    !34   ; (*I.)
        =       nfs_cmd,    "I",       !19   ; (*I .)
 [ $False
        =       ut_cmd,     "LIST",    !21   ; (*LI.)
 ]
        =       nondfs_cmd, "LIB",     !10   ; (*LIB)
        =       fs_cmd,     "LIB",     !31   ; (*LIB)
        =       adfs_cmd :OR: arfs_cmd, "MOUNT",!27 ; (*MOU.)
        =       ut_cmd,     "NET",     !05   ; (*N.)
        =       ut_cmd,     "OS",      !02   ; (*OS)
        =       ut_cmd,     "QUIT",    !00   ; (*Q.)
        =       fs_cmd,     "RENAME",  !17   ; (*RE.)
        =       nondfs_cmd, "REMOVE",  !15   ; (*REM.)
        =       ut_cmd,     "RESET",   !03   ; (*RES.)
        =       dfs_cmd :OR: adfs_cmd :OR: arfs_cmd, "TITLE",!24 ; (*TI.)
 [ $False
        =       ut_cmd,     "TYPE",    !16   ; (*TY.)
 ]
        =       &00                     ; End of table (no valid caller)

; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

comrouts
        &       quit_star-1             ; 00
        &       go_star-1               ; 01
        &       os_star-1               ; 02
        &       reset_star-1            ; 03
        &       disc_star-1             ; 04
        &       net_star-1              ; 05
        &       enable_d_star-1         ; 06
        &       arfs_star-1             ; 07
        &       adfs_star-1             ; 08
        &       dir_star-1              ; 09
        &       lib_star-1              ; 10
        &       drive_d_star-1          ; 11
        &       access_star-1           ; 12
        &       info_star-1             ; 13
        &       delete_star-1           ; 14
        &       remove_star-1           ; 15
 [ $False
        &       type_star-1             ; 16
 |
        &       -1                      ; 16
 ]
        &       rename_star-1           ; 17
        &       create_star-1           ; 18
        &       i_star-1                ; 19
        &       close_star-1            ; 20
 [ $False
        &       list_star-1             ; 21
 |
        &       -1                      ; 21
 ]
        &       back_star-1             ; 22
        &       cdir_star-1             ; 23
        &       title_star-1            ; 24
        &       bye_star-1              ; 25
        &       compact_star-1          ; 26
        &       mount_star-1            ; 27
        &       dismount_star-1         ; 28
        &       ex_star-1               ; 29
        &       dir_d_star-1            ; 30
        &       lib_d_star-1            ; 31
        &       ex_d_star-1             ; 32
        &       comp_d_star-1           ; 33
        &       info_d_star-1           ; 34
        &       acc_d_star-1            ; 35
        &       del_d_star-1            ; 36

syntable
        &       /syu_quit               ; 00
        &       /syu_go                 ; 01
        &       /syu_os                 ; 02
        &       /syu_reset              ; 03
        &       /syu_disc               ; 04
        &       /syu_net                ; 05
        &       /syd_enable             ; 06
        &       /syu_arfs               ; 07
        &       /syu_adfs               ; 08
        &       /syf_dir                ; 09
        &       /syf_lib                ; 10
        &       /syd_drive              ; 11
        &       /syf_access             ; 12
        &       /syf_info               ; 13
        &       /syf_delete             ; 14
        &       /syf_remove             ; 15
 [ $False
        &       /syu_type               ; 16
 |
        &       /-1                     ; 16
 ]
        &       /syf_rename             ; 17
        &       /syu_create             ; 18
        &       /syn_i                  ; 19
        &       /syu_close              ; 20
 [ $False
        &       /syu_list               ; 21
 |
        &       /-1                     ; 21
 ]
        &       /syf_back               ; 22
        &       /syf_cdir               ; 23
        &       /syf_title              ; 24
        &       /syf_bye                ; 25
        &       /syf_compact            ; 26
        &       /syf_mount              ; 27
        &       /syf_dismount           ; 28
        &       /syf_ex                 ; 29
        &       /syd_dir                ; 30
        &       /syd_lib                ; 31
        &       /syd_ex                 ; 32
        &       /syd_compact            ; 33
        &       /syd_info               ; 34
        &       /syd_access             ; 35
        &       /syd_delete             ; 36

syu_quit * 0
syu_os * 0
syu_disc * 0
syu_net * 0
syu_arfs * 0
syu_adfs * 0
syu_close * 0
syu_go       =  "(<hex address>)", CR
syu_reset    =  "(<number>)", CR
syu_create   =  "<filename> <length> (<exec> (<load>))", CR
 [ $False
syu_type  =     "<filename>", CR
syu_list  * syu_type
 ]


syd_compact  *  0
syd_enable   *  0
syd_dir      =  "(<dir>)", CR
syd_lib      *  syd_dir
syd_ex       *  syd_dir

syd_info     =  "<filename>", CR
syd_delete   *  syd_info

syd_drive    =  "<drive>", CR
syd_access   =  "<afsp> (L)", CR

syn_i        =  "AM <username> <password>", CR


syf_back     *  0
syf_bye      *  0
syf_compact  *  0
syf_dir      =  "(<directory>)", CR
syf_lib      *  syf_dir
syf_ex       *  syf_dir

syf_cdir     =  "<directory>", CR
syf_title    =  "(<title>)", CR

syf_mount    =  "(<drive>)", CR
syf_dismount *  syf_mount

syf_info     =  "<object>", CR
syf_delete   *  syf_info
syf_remove   *  syf_info

syf_rename =    "<object> <object>", CR
syf_access =    "<object> <attributes>", CR

; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

        LNK     FS20
